In [ ]:
%%HTML
<style>
.container { width:100% }
</style>
The module heapq provides priority queues that are implemented as heaps. Technically, these heaps are just lists. In order to use them as priority queues, the entries of these lists will be pairs of the form $(p, o)$, where $p$ is the priority of the object $o$. Usually, the priorities are numbers and, contra-intuitively, high priorities correspond to small numbers, that is $(p_1, o_1)$ has a higher priority than $(p_2, o_2)$ iff $p_1 < p_2$.
We need only two functions from the module heapq:
In [ ]:
import heapq
The function search takes three arguments to solve a search problem:
start is the start state of the search problem,goalis the goal state, andnext_states is a function with signature $\texttt{next_states}:Q \rightarrow 2^Q$, where $Q$ is the set of states.
For every state $s \in Q$, $\texttt{next_states}(s)$ is the set of states that can be reached from $s$ in one step.heuristic is a function that takes two states as arguments. It returns an estimate of the
length of the shortest path between these states.
If successful, search returns a path from start to goal that is a solution of the search problem
$$ \langle Q, \texttt{next_states}, \texttt{start}, \texttt{goal} \rangle. $$The variable PrioQueue that is used in the implementation contains pairs of the form
$$ \bigl(\texttt{len}(\texttt{Path}) + \texttt{heuristic}(\texttt{state},\; \texttt{goal}), \texttt{Path}\bigr), $$
where Path is a path from start to state and $\texttt{heuristic}(\texttt{state}, \texttt{goal})$
is an estimate of the distance from state to goal. The idea is to always extend the most promising Path, i.e. to extend the Path whose completed version would be shortest.
In [ ]:
def search(start, goal, next_states, heuristic):
PrioQueue = [ (heuristic(start, goal), [start]) ]
while len(PrioQueue) > 0:
_, Path = heapq.heappop(PrioQueue)
state = Path[-1]
if state == goal:
return Path
for ns in next_states(state):
if ns not in Path:
prio = heuristic(ns, goal) + len(Path)
heapq.heappush(PrioQueue, (prio, Path + [ns]))
In [ ]:
%run Sliding-Puzzle.ipynb
In [ ]:
%%time
Path = search(start, goal, next_states, manhattan)
print(len(Path)-1)
In [ ]:
animation(Path)
In [ ]:
%%time
Path = search(start2, goal2, next_states, manhattan)
print(len(Path)-1)
In [ ]:
animation(Path)
In [ ]: